#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File        :Project_CAN.py
@Desc        :
@Time        :2022/06/17 16:42:11
@Author        :WangWei
'''
import sys
import os
import logging
import hashlib
import binascii
import allure
import Set_up
import datetime
import time
from pytest_assume.plugin import assume
import numpy as np
from Crypto.Cipher import AES
from Crypto.Hash import CMAC
from binascii import hexlify, unhexlify
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.abspath(os.path.dirname(curPath) + os.path.sep + ".")
sys.path.append(rootPath)
sys.path.append(os.path.join(curPath,'commDriver'))
sys.path.append(os.path.join(curPath,'data'))

from functools import reduce
from commDriver.TS_CAN import TSCAN, TSCAN_UDS,HIL_Obj
from commDriver.TS_CAN import TSMasterAPI
from commDriver.modbus_plc import *


#BE12
BCM_0x2D2 = [Set_up.NetName,Set_up.nodeName,'BCM_0x2D2']
BCM_0x2F1 = [Set_up.NetName,Set_up.nodeName,'BCM_0x2F1']
ECC_0x3F2 = [Set_up.NetName,Set_up.nodeName,'ECC_0x3F2']
EPS_0x150 = [Set_up.NetName,Set_up.nodeName,'EPS_0x150']
ICC_0x31F = [Set_up.NetName,Set_up.nodeName,'ICC_0x31F']
ICC_0x3FE = [Set_up.NetName,Set_up.nodeName,'ICC_0x3FE']
ICM_0x2E0 = [Set_up.NetName,Set_up.nodeName,'ICM_0x2E0']
PBM_0x183 = [Set_up.NetName,Set_up.nodeName,'PBM_0x183']
PBM_0x185 = [Set_up.NetName,Set_up.nodeName,'PBM_0x185']
PBM_0x186 = [Set_up.NetName,Set_up.nodeName,'PBM_0x186']
PBM_0x1A6 = [Set_up.NetName,Set_up.nodeName,'PBM_0x1A6']
PEPS_0x1B1 = [Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1']
TBOX_0x551 = [Set_up.NetName,Set_up.nodeName,'TBOX_0x551']
VCU_PDCU_0x230 = [Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230']
VCU_0x26C = [Set_up.NetName,Set_up.nodeName,'VCU_0x26C']
YRS_0x19A = [Set_up.NetName,Set_up.nodeName,'YRS_0x19A']


check_ID_List_FL = [0x200,0x201,0x202,0x203,0x204,0x205,0x206,0x207,0x208,0x209,0x20A,0x20B,0x20C,0x20D,0x20E,0x20F] 
check_ID_List_FR = [0x240,0x241,0x242,0x243,0x244,0x245,0x246,0x247,0x248,0x249,0x24A,0x24B,0x24C,0x24D,0x24E,0x24F]
check_ID_List_RL = [0x280,0x281,0x282,0x283,0x284,0x285,0x286,0x287,0x288,0x289,0x28A,0x28B,0x28C,0x28D,0x28E,0x28F]
check_ID_List_RR = [0x2C0,0x2C1,0x2C2,0x2C3,0x2C4,0x2C5,0x2C6,0x2C7,0x2C8,0x2C9,0x2CA,0x2CB,0x2CC,0x2CD,0x2CE,0x2CF]
check_ID_List =check_ID_List_FL+check_ID_List_FR+check_ID_List_RL+check_ID_List_RR

def On_CANFD_EVENT(OBJ, ACAN):
    if ((ACAN.contents.FIdentifier == 0x7CC or ACAN.contents.FIdentifier == 0x7C9) and ACAN.contents.FIdxChn == 0):
        if ACAN.contents.FData[1] == 0x7F and ACAN.contents.FData[3] == 0x78:
            logging.info("收到NRC78")

    if (ACAN.contents.FIdentifier == 0x666 and ACAN.contents.FIdxChn == 0):
        # print("CANFD 0x666 回调接收成功")
        # for i in ACAN.contents.FData:
        #     print('%#x' % i, end=' ')
        # print('')
        pass
    if (ACAN.contents.FIdentifier == 0x777 and ACAN.contents.FIdxChn == 0):
        # print("CAN 0x777 回调接收成功")
        # for i in ACAN.contents.FData:
        #     print('%#x' % i, end=' ')
        # logging.info('')
        pass
OnCANFDevent = TSMasterAPI.OnTx_RxFUNC_CANFD(On_CANFD_EVENT)

Enable_0x311_RollingCounter_Error = False
Enable_0x311_Checksum_Error = False
Enable_0x570_RollingCounter_Error = False
Enable_0x570_Checksum_Error = False
Enable_0x3E0_RollingCounter_Error = False
Enable_0x3E0_Checksum_Error = False

# BE12
Enable_0x2F1_RollingCounter_Error = False
Enable_0x2F1_Checksum_Error = False

Enable_0x183_RollingCounter_Error = False
Enable_0x183_Checksum_Error = False

Enable_0x185_RollingCounter_Error = False
Enable_0x185_Checksum_Error = False

Enable_0x186_RollingCounter_Error = False
Enable_0x186_Checksum_Error = False

Enable_0x230_RollingCounter_Error = False
Enable_0x230_Checksum_Error = False

Enable_0x210_RollingCounter_Error = False
Enable_0x210_Checksum_Error = False

Enable_0x19A_RollingCounter_Error = False
Enable_0x19A_Checksum_Error = False

Enable_0x1B1_RollingCounter_Error = False
Enable_0x1B1_Checksum_Error = False

Enable_0x150_RollingCounter_Error = False
Enable_0x150_Checksum_Error = False

'''计算CRC值'''
def CalCRC8(data):
    polynomial = 0x1A
    initValue = 0x00
    xorValue = 0x00
    for i in range(len(data)):
        initValue = initValue ^ data[i]
        for j in range(8):
            if(initValue & 0x80):
                initValue = ((initValue << 1) & 0xff)
                initValue = initValue ^ polynomial
            else:
                initValue = ((initValue << 1) & 0xff)
    initValue = initValue ^ xorValue
    return initValue

def CalCRC16(data):
    """
    计算CRC-16校验值
    :param data: 输入数据，字节串
    :return: CRC-16校验值
    """
    polynomial = 0x1021  # 多项式
    initial_value = 0xFFFF  # 初始值
    xor_out = 0x0000  # XOR输出

    crc = initial_value
    for byte in data:
        crc ^= (byte << 8)
        for _ in range(8):
            if crc & 0x8000:
                crc = (crc << 1) ^ polynomial
            else:
                crc <<= 1
        crc &= 0xFFFF
    return crc ^ xor_out


from functools import reduce

def crc8_sae_j1850(data, dataID):
    crc = 0x00
    polynomial = 0x1D

    calcData = []
    calcData.append(dataID[1])
    calcData.append(dataID[0])
    for i in range(len(data)):
        calcData.append(data[i])

    # logging.info("calcData: %s", calcData)
    

    for byte in calcData:
        crc ^= byte
        for _ in range(8):
            if crc & 0x80:
                crc = (crc << 1) ^ polynomial
            else:
                crc <<= 1
        crc &= 0xFF
    crc = crc ^ 0x00

    return crc

def On_CANFD_EVENT_Pre(OBJ, ACAN):
    global Enable_0x311_RollingCounter_Error
    global Enable_0x311_Checksum_Error
    global Enable_0x570_RollingCounter_Error
    global Enable_0x570_Checksum_Error
    global Enable_0x3E0_RollingCounter_Error
    global Enable_0x3E0_Checksum_Error

    #BE12
    global Enable_0x2F1_Checksum_Error
    global Enable_0x2F1_RollingCounter_Error

    global Enable_0x183_Checksum_Error
    global Enable_0x183_RollingCounter_Error

    global Enable_0x185_Checksum_Error
    global Enable_0x185_RollingCounter_Error

    global Enable_0x186_Checksum_Error
    global Enable_0x186_RollingCounter_Error

    global Enable_0x230_Checksum_Error
    global Enable_0x230_RollingCounter_Error

    global Enable_0x210_Checksum_Error
    global Enable_0x210_RollingCounter_Error

    global Enable_0x19A_Checksum_Error
    global Enable_0x19A_RollingCounter_Error

    global Enable_0x1B1_Checksum_Error
    global Enable_0x1B1_RollingCounter_Error
    
    global Enable_0x150_Checksum_Error
    global Enable_0x150_RollingCounter_Error

    if (ACAN.contents.FIdentifier == 0x2F1 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x2F1_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        ACAN.contents.FData[17] = ACAN.contents.FData[17] & 0xF0 | a
        ACAN.contents.FData[25] = ACAN.contents.FData[25] & 0xF0 | a
        ACAN.contents.FData[33] = ACAN.contents.FData[33] & 0xF0 | a
        ACAN.contents.FData[41] = ACAN.contents.FData[41] & 0xF0 | a
        ACAN.contents.FData[49] = ACAN.contents.FData[49] & 0xF0 | a
        # Checksum
        if Enable_0x2F1_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x38])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x1C])
            ACAN.contents.FData[16] = crc8_sae_j1850(ACAN.contents.FData[17:24], [0x00,0x3B])
            ACAN.contents.FData[24] = crc8_sae_j1850(ACAN.contents.FData[25:32], [0x00,0x3C])
            ACAN.contents.FData[32] = crc8_sae_j1850(ACAN.contents.FData[33:40], [0x00,0x66])
            ACAN.contents.FData[40] = crc8_sae_j1850(ACAN.contents.FData[41:48], [0x00,0x67])
            ACAN.contents.FData[48] = crc8_sae_j1850(ACAN.contents.FData[49:56], [0x00,0x68])   
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0
            ACAN.contents.FData[16] = 0
            ACAN.contents.FData[24] = 0
            ACAN.contents.FData[32] = 0
            ACAN.contents.FData[40] = 0
            ACAN.contents.FData[48] = 0
    
    if (ACAN.contents.FIdentifier == 0x183 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x183_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        # Checksum
        if Enable_0x183_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x0E])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x0F])  
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0
    
    if (ACAN.contents.FIdentifier == 0x185 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x185_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        ACAN.contents.FData[17] = ACAN.contents.FData[17] & 0xF0 | a
        ACAN.contents.FData[25] = ACAN.contents.FData[25] & 0xF0 | a
        # Checksum
        if Enable_0x185_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x01])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x02]) 
            ACAN.contents.FData[16] = crc8_sae_j1850(ACAN.contents.FData[17:24], [0x00,0x03])  
            ACAN.contents.FData[24] = crc8_sae_j1850(ACAN.contents.FData[25:32], [0x00,0x04])   
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0
            ACAN.contents.FData[16] = 0
            ACAN.contents.FData[24] = 0

    if (ACAN.contents.FIdentifier == 0x186 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x186_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        # Checksum
        if Enable_0x186_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x06])
        else:
            ACAN.contents.FData[0] = 0

    if (ACAN.contents.FIdentifier == 0x230 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x230_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        # Checksum
        if Enable_0x230_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x55])
        else:
            ACAN.contents.FData[0] = 0

    if (ACAN.contents.FIdentifier == 0x210 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x210_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        # Checksum
        if Enable_0x210_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x53])
        else:
            ACAN.contents.FData[0] = 0

    if (ACAN.contents.FIdentifier == 0x19A and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x19A_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        # Checksum
        if Enable_0x19A_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x1F])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x20])
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0

    if (ACAN.contents.FIdentifier == 0x1B1 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x1B1_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        ACAN.contents.FData[17] = ACAN.contents.FData[17] & 0xF0 | a
        ACAN.contents.FData[25] = ACAN.contents.FData[25] & 0xF0 | a
        ACAN.contents.FData[33] = ACAN.contents.FData[33] & 0xF0 | a
        # Checksum
        if Enable_0x1B1_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x31])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x39])
            ACAN.contents.FData[16] = crc8_sae_j1850(ACAN.contents.FData[17:24], [0x00,0x69])
            ACAN.contents.FData[24] = crc8_sae_j1850(ACAN.contents.FData[25:32], [0x00,0x70])
            ACAN.contents.FData[32] = crc8_sae_j1850(ACAN.contents.FData[33:40], [0x00,0x71])
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0
            ACAN.contents.FData[16] = 0
            ACAN.contents.FData[24] = 0
            ACAN.contents.FData[32] = 0

    if (ACAN.contents.FIdentifier == 0x150 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        if Enable_0x150_RollingCounter_Error != True:
            a = ACAN.contents.FData[1] & 0xF  # FData 字节数组int类型
            a += 1
            if a > 14:
                a = 0
        else:
            a = 0
        ACAN.contents.FData[1] = ACAN.contents.FData[1] & 0xF0 | a
        ACAN.contents.FData[9] = ACAN.contents.FData[9] & 0xF0 | a
        # Checksum
        if Enable_0x150_Checksum_Error != True:
            ACAN.contents.FData[0] = crc8_sae_j1850(ACAN.contents.FData[1:8], [0x00,0x1E])
            ACAN.contents.FData[8] = crc8_sae_j1850(ACAN.contents.FData[9:16], [0x00,0x22])
        else:
            ACAN.contents.FData[0] = 0
            ACAN.contents.FData[8] = 0


    if (ACAN.contents.FIdentifier == 0x570 and ACAN.contents.FIdxChn == 0):
#         # RollingCounter
#         if Enable_0x311_RollingCounter_Error != True:
#             a = ACAN.contents.FData[0]  # FData 字节数组int类型
#             a += 1
#             if a > 15:
#                 a = 0
#             ACAN.contents.FData[0] = a
#         else:
#             ACAN.contents.FData[0] = 0
        # Checksum
        if Enable_0x570_Checksum_Error != True:
            list_num = ACAN.contents.FData[0:7]
            ACAN.contents.FData[7] = reduce(lambda x, y: x + y, list_num) & 0xFF
        else:
            ACAN.contents.FData[7] = 0

    if (ACAN.contents.FIdentifier == 0x3E0 and ACAN.contents.FIdxChn == 0):
#         # RollingCounter
#         if Enable_0x311_RollingCounter_Error != True:
#             a = ACAN.contents.FData[0]  # FData 字节数组int类型
#             a += 1
#             if a > 15:
#                 a = 0
#             ACAN.contents.FData[0] = a
#         else:
#             ACAN.contents.FData[0] = 0
        # Checksum
        if Enable_0x3E0_Checksum_Error != True:
            list_num = ACAN.contents.FData[0:7]
            ACAN.contents.FData[7] = reduce(lambda x, y: x + y, list_num) & 0xFF
        else:
            ACAN.contents.FData[7] = 0

    if (ACAN.contents.FIdentifier == 0x384 and ACAN.contents.FIdxChn == 0):
#         # RollingCounter
#         if Enable_0x311_RollingCounter_Error != True:
#             a = ACAN.contents.FData[0]  # FData 字节数组int类型
#             a += 1
#             if a > 15:
#                 a = 0
#             ACAN.contents.FData[0] = a
#         else:
#             ACAN.contents.FData[0] = 0
        # Checksum
        act_checksum = ACAN.contents.FData[0]
        exc_checksum = sum(ACAN.contents.FData[1:8]) & 0xFF
        if act_checksum != exc_checksum:
            logging.info(f'0x384 act_checksum: {hex(act_checksum)}')
            logging.info(f'0x384 exc_checksum:{hex(exc_checksum)}')
        with assume: assert act_checksum == exc_checksum   

    if (ACAN.contents.FIdentifier == 0x385 and ACAN.contents.FIdxChn == 0):
#         # RollingCounter
#         if Enable_0x311_RollingCounter_Error != True:
#             a = ACAN.contents.FData[0]  # FData 字节数组int类型
#             a += 1
#             if a > 15:
#                 a = 0
#             ACAN.contents.FData[0] = a
#         else:
#             ACAN.contents.FData[0] = 0
        # Checksum
        act_checksum = ACAN.contents.FData[0]
        exc_checksum = sum(ACAN.contents.FData[1:8]) & 0xFF
        if act_checksum != exc_checksum:
            logging.info(f'0x385 act_checksum: {hex(act_checksum)}')
            logging.info(f'0x385 exc_checksum:{hex(exc_checksum)}')
        with assume: assert act_checksum == exc_checksum   

    if (ACAN.contents.FIdentifier == 0x386 and ACAN.contents.FIdxChn == 0):
#         # RollingCounter
#         if Enable_0x311_RollingCounter_Error != True:
#             a = ACAN.contents.FData[0]  # FData 字节数组int类型
#             a += 1
#             if a > 15:
#                 a = 0
#             ACAN.contents.FData[0] = a
#         else:
#             ACAN.contents.FData[0] = 0
        # Checksum
        act_checksum = ACAN.contents.FData[0]
        exc_checksum = sum(ACAN.contents.FData[1:8]) & 0xFF
        if act_checksum != exc_checksum:
            logging.info(f'0x386 act_checksum: {hex(act_checksum)}')
            logging.info(f'0x386 exc_checksum:{hex(exc_checksum)}')
        with assume: assert act_checksum == exc_checksum   

OnCANPreFDevent = TSMasterAPI.OnTx_RxFUNC_CANFD(On_CANFD_EVENT_Pre)

def On_CANFD_EVENT_PCAN_Front(OBJ, ACAN):
    current_ID = ACAN.contents.FIdentifier
    if current_ID in check_ID_List:
    # if (ACAN.contents.FIdentifier == 0x200 and ACAN.contents.FIdxChn == 0):
        # RollingCounter
        # act_crc = ACAN.contents.FData[23] & 0xF  # FData 字节数组int类型
        # if flag:
        #     exc_crc = act_crc
        # else:
        #     exc_crc += 1
        #     if exc_crc > 15:
        #         exc_crc = 0
        # with assume: act_crc == exc_crc
        
        # # Checksum
        # act_checksum = ACAN.contents.FData[0]
        # exc_checksum = sum(ACAN.contents.FData[1:24]) ^ 0xFF
        # logging.info(f'exc_checksum:{exc_checksum}')
        # with assume: act_checksum == exc_checksum
        pass

OnCANPreFDevent_PCAN_Front = TSMasterAPI.OnTx_RxFUNC_CANFD(On_CANFD_EVENT_PCAN_Front)

class real_CAN(TSCAN):

    # def set_0x311_rolling_counter_error(self,enable=False):
    #     global Enable_0x311_RollingCounter_Error
    #     if enable:
    #         Enable_0x311_RollingCounter_Error = True
    #     else:
    #         Enable_0x311_RollingCounter_Error = False
    
    def set_0x311_checksum_error(self,enable=False):
        global Enable_0x311_Checksum_Error
        if enable:
            Enable_0x311_Checksum_Error = True
        else:
            Enable_0x311_Checksum_Error = False

    # def set_0x570_rolling_counter_error(self,enable=False):
    #     global Enable_0x570_RollingCounter_Error
    #     if enable:
    #         Enable_0x570_RollingCounter_Error = True
    #     else:
    #         Enable_0x570_RollingCounter_Error = False
    
    def set_0x570_checksum_error(self,enable=False):
        global Enable_0x570_Checksum_Error
        if enable:
            Enable_0x570_Checksum_Error = True
        else:
            Enable_0x570_Checksum_Error = False

    # def set_0x3E0_rolling_counter_error(self,enable=False):
    #     global Enable_0x3E0_RollingCounter_Error
    #     if enable:
    #         Enable_0x3E0_RollingCounter_Error = True
    #     else:
    #         Enable_0x3E0_RollingCounter_Error = False
    
    def set_0x3E0_checksum_error(self,enable=False):
        global Enable_0x3E0_Checksum_Error
        if enable:
            Enable_0x3E0_Checksum_Error = True
        else:
            Enable_0x3E0_Checksum_Error = False

    #BE12
    def set_0x2D2_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,BCM_0x2D2[0],BCM_0x2D2[1],BCM_0x2D2[2],False)
        else:
            TSCAN.Enable_rbs_message(self,BCM_0x2D2[0],BCM_0x2D2[1],BCM_0x2D2[2],True)

    def set_0x2F1_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,BCM_0x2F1[0],BCM_0x2F1[1],BCM_0x2F1[2],False)
        else:
            TSCAN.Enable_rbs_message(self,BCM_0x2F1[0],BCM_0x2F1[1],BCM_0x2F1[2],True)

    def set_0x3F2_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,ECC_0x3F2[0],ECC_0x3F2[1],ECC_0x3F2[2],False)
        else:
            TSCAN.Enable_rbs_message(self,ECC_0x3F2[0],ECC_0x3F2[1],ECC_0x3F2[2],True)
    
    def set_0x150_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,EPS_0x150[0],EPS_0x150[1],EPS_0x150[2],False)
        else:
            TSCAN.Enable_rbs_message(self,EPS_0x150[0],EPS_0x150[1],EPS_0x150[2],True)

    def set_0x31F_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,ICC_0x31F[0],ICC_0x31F[1],ICC_0x31F[2],False)
        else:
            TSCAN.Enable_rbs_message(self,ICC_0x31F[0],ICC_0x31F[1],ICC_0x31F[2],True)

    def set_0x3FE_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,ICC_0x3FE[0],ICC_0x3FE[1],ICC_0x3FE[2],False)
        else:
            TSCAN.Enable_rbs_message(self,ICC_0x3FE[0],ICC_0x3FE[1],ICC_0x3FE[2],True)

    def set_0x2E0_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,ICM_0x2E0[0],ICM_0x2E0[1],ICM_0x2E0[2],False)
        else:
            TSCAN.Enable_rbs_message(self,ICM_0x2E0[0],ICM_0x2E0[1],ICM_0x2E0[2],True)

    def set_0x183_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,PBM_0x183[0],PBM_0x183[1],PBM_0x183[2],False)
        else:
            TSCAN.Enable_rbs_message(self,PBM_0x183[0],PBM_0x183[1],PBM_0x183[2],True)

    def set_0x185_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,PBM_0x185[0],PBM_0x185[1],PBM_0x185[2],False)
        else:
            TSCAN.Enable_rbs_message(self,PBM_0x185[0],PBM_0x185[1],PBM_0x185[2],True)

    def set_0x186_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,PBM_0x186[0],PBM_0x186[1],PBM_0x186[2],False)
        else:
            TSCAN.Enable_rbs_message(self,PBM_0x186[0],PBM_0x186[1],PBM_0x186[2],True)

    def set_0x1A6_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,PBM_0x1A6[0],PBM_0x1A6[1],PBM_0x1A6[2],False)
        else:
            TSCAN.Enable_rbs_message(self,PBM_0x1A6[0],PBM_0x1A6[1],PBM_0x1A6[2],True)

    def set_0x1B1_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,PEPS_0x1B1[0],PEPS_0x1B1[1],PEPS_0x1B1[2],False)
        else:
            TSCAN.Enable_rbs_message(self,PEPS_0x1B1[0],PEPS_0x1B1[1],PEPS_0x1B1[2],True)

    def set_0x551_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,TBOX_0x551[0],TBOX_0x551[1],TBOX_0x551[2],False)
        else:
            TSCAN.Enable_rbs_message(self,TBOX_0x551[0],TBOX_0x551[1],TBOX_0x551[2],True)

    def set_0x230_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,VCU_PDCU_0x230[0],VCU_PDCU_0x230[1],VCU_PDCU_0x230[2],False)
        else:
            TSCAN.Enable_rbs_message(self,VCU_PDCU_0x230[0],VCU_PDCU_0x230[1],VCU_PDCU_0x230[2],True)

    def set_0x26C_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,VCU_0x26C[0],VCU_0x26C[1],VCU_0x26C[2],False)
        else:
            TSCAN.Enable_rbs_message(self,VCU_0x26C[0],VCU_0x26C[1],VCU_0x26C[2],True)

    def set_0x19A_lost_error(self,enable=False):
        if enable:
            TSCAN.Enable_rbs_message(self,YRS_0x19A[0],YRS_0x19A[1],YRS_0x19A[2],False)
        else:
            TSCAN.Enable_rbs_message(self,YRS_0x19A[0],YRS_0x19A[1],YRS_0x19A[2],True)

    
    def set_0x2F1_checksum_error(self,enable=False):
        global Enable_0x2F1_Checksum_Error
        if enable:
            logging.info("Set 0x2F1 Checksum mistake")
            Enable_0x2F1_Checksum_Error = True
        else:
            logging.info("Set 0x2F1 Checksum correct")
            Enable_0x2F1_Checksum_Error = False 

    def set_0x2F1_rolling_counter_error(self,enable=False):
        global Enable_0x2F1_RollingCounter_Error
        if enable:
            logging.info("Set 0x2F1 Rolling Counter Failed")
            Enable_0x2F1_RollingCounter_Error = True
        else:
            logging.info("Set 0x2F1 Rolling Counter True")
            Enable_0x2F1_RollingCounter_Error = False 


    def set_0x183_checksum_error(self,enable=False):
        global Enable_0x183_Checksum_Error
        if enable:
            logging.info("Set 0x183 Checksum mistake")
            Enable_0x183_Checksum_Error = True
        else:
            logging.info("Set 0x183 Checksum correct")
            Enable_0x183_Checksum_Error = False 

    def set_0x183_rolling_counter_error(self,enable=False):
        global Enable_0x183_RollingCounter_Error
        if enable:
            logging.info("Set 0x183 Rolling Counter Failed")
            Enable_0x183_RollingCounter_Error = True
        else:
            logging.info("Set 0x183 Rolling Counter True")
            Enable_0x183_RollingCounter_Error = False 

    def set_0x185_checksum_error(self,enable=False):
        global Enable_0x185_Checksum_Error
        if enable:
            logging.info("Set 0x185 Checksum mistake")
            Enable_0x185_Checksum_Error = True
        else:
            logging.info("Set 0x185 Checksum correct")
            Enable_0x185_Checksum_Error = False 

    def set_0x185_rolling_counter_error(self,enable=False):
        global Enable_0x185_RollingCounter_Error
        if enable:
            logging.info("Set 0x185 Rolling Counter Failed")
            Enable_0x185_RollingCounter_Error = True
        else:
            logging.info("Set 0x185 Rolling Counter True")
            Enable_0x185_RollingCounter_Error = False 
    
    def set_0x186_checksum_error(self,enable=False):
        global Enable_0x186_Checksum_Error
        if enable:
            logging.info("Set 0x186 Checksum mistake")
            Enable_0x186_Checksum_Error = True
        else:
            logging.info("Set 0x186 Checksum correct")
            Enable_0x186_Checksum_Error = False 

    def set_0x186_rolling_counter_error(self,enable=False):
        global Enable_0x186_RollingCounter_Error
        if enable:
            logging.info("Set 0x186 Rolling Counter Failed")
            Enable_0x186_RollingCounter_Error = True
        else:
            logging.info("Set 0x186 Rolling Counter True")
            Enable_0x186_RollingCounter_Error = False 

    def set_0x230_checksum_error(self,enable=False):
        global Enable_0x230_Checksum_Error
        if enable:
            logging.info("Set 0x230 Checksum mistake")
            Enable_0x230_Checksum_Error = True
        else:
            logging.info("Set 0x230 Checksum correct")
            Enable_0x230_Checksum_Error = False 

    def set_0x230_rolling_counter_error(self,enable=False):
        global Enable_0x230_RollingCounter_Error
        if enable:
            logging.info("Set 0x230 Rolling Counter Failed")
            Enable_0x230_RollingCounter_Error = True
        else:
            logging.info("Set 0x230 Rolling Counter True")
            Enable_0x230_RollingCounter_Error = False 

    def set_0x210_checksum_error(self,enable=False):
        global Enable_0x210_Checksum_Error
        if enable:
            logging.info("Set 0x210 Checksum mistake")
            Enable_0x210_Checksum_Error = True
        else:
            logging.info("Set 0x210 Checksum correct")
            Enable_0x210_Checksum_Error = False 

    def set_0x210_rolling_counter_error(self,enable=False):
        global Enable_0x210_RollingCounter_Error
        if enable:
            logging.info("Set 0x210 Rolling Counter Failed")
            Enable_0x210_RollingCounter_Error = True
        else:
            logging.info("Set 0x210 Rolling Counter True")
            Enable_0x210_RollingCounter_Error = False 

    def set_0x19A_checksum_error(self,enable=False):
        global Enable_0x19A_Checksum_Error
        if enable:
            logging.info("Set 0x19A Checksum mistake")
            Enable_0x19A_Checksum_Error = True
        else:
            logging.info("Set 0x19A Checksum correct")
            Enable_0x19A_Checksum_Error = False 

    def set_0x19A_rolling_counter_error(self,enable=False):
        global Enable_0x19A_RollingCounter_Error
        if enable:
            logging.info("Set 0x19A Rolling Counter Failed")
            Enable_0x19A_RollingCounter_Error = True
        else:
            logging.info("Set 0x19A Rolling Counter True")
            Enable_0x19A_RollingCounter_Error = False 

    def set_0x1B1_checksum_error(self,enable=False):
        global Enable_0x1B1_Checksum_Error
        if enable:
            logging.info("Set 0x1B1 Checksum mistake")
            Enable_0x1B1_Checksum_Error = True
        else:
            logging.info("Set 0x1B1 Checksum correct")
            Enable_0x1B1_Checksum_Error = False 

    def set_0x1B1_rolling_counter_error(self,enable=False):
        global Enable_0x1B1_RollingCounter_Error
        if enable:
            logging.info("Set 0x1B1 Rolling Counter Failed")
            Enable_0x1B1_RollingCounter_Error = True
        else:
            logging.info("Set 0x1B1 Rolling Counter True")
            Enable_0x1B1_RollingCounter_Error = False 
    
    def set_0x150_checksum_error(self,enable=False):
        global Enable_0x150_Checksum_Error
        if enable:
            logging.info("Set 0x150 Checksum mistake")
            Enable_0x150_Checksum_Error = True
        else:
            logging.info("Set 0x150 Checksum correct")
            Enable_0x150_Checksum_Error = False 

    def set_0x150_rolling_counter_error(self,enable=False):
        global Enable_0x150_RollingCounter_Error
        if enable:
            logging.info("Set 0x150 Rolling Counter Failed")
            Enable_0x150_RollingCounter_Error = True
        else:
            logging.info("Set 0x150 Rolling Counter True")
            Enable_0x150_RollingCounter_Error = False 


    def set_signal_Year(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Yr',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Yr')

    def set_signal_Month(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Mth',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Mth')

    def set_signal_Day(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Day',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Day')

    def set_signal_Hour(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Hr',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Hr')

    def set_signal_Minute(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Mins',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Mins')
    
    def set_signal_Second(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Sec',value)   # 0x551
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'TBOX_0x551','TBOX_CrtTi_Sec')
    
    def set_signal_EMS5_St_EngineRunning(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'EMS_5','EMS5_St_EngineRunning',value)   # 0x280
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'EMS_5','EMS5_St_EngineRunning')

    def set_signal_VehStop(self,value):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehStop',value)   # 0x280
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehStop')    #0x0:Not standstill, 0x1:Standstill, 0x2:Invalid, 0x3:Reserved

    def set_signal_Speed(self,value): 
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehSpdVld',1)   # 0x311
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehSpdVld')  # 0x0:Initializing, 0x1:Valid, 0x2:Invalid, 0x3:Reserved
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehSpd',value) #1.0125--0x0012,2.025----0x024,2.98125---0x0035
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x185','VehSpd')

    def set_signal_IGN(self,value): 
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrModVld',0x02)
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrModVld')  # 0x0:Reserved, 0x1:Invalid, 0x2:Valid, 0x3：reserved
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrMod',value)
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrMod')

    def set_signal_Gear(self,value): 
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230','VCU_STRATEGY_SHIFT_POSN_FLAG',0)  # 0x3E0  # 0x0: Value OK,0x1/0x02: Not used,0x3: Value unreliable
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230','VCU_STRATEGY_SHIFT_POSN_FLAG') 
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230','VCU_STRATEGY_SHIFT_POSITION',value)  # 0x3E0
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230','VCU_STRATEGY_SHIFT_POSITION')  # 0x0: Void, 0x1: P,0x2: N,0x3: R,0x4: D,0x5: Void,0x6: E,0x7: S

    def set_signal_ADAS_rear(self,DowSwt,Bsd_LcaSwt,RctaSwt,RctbSwt,RcwSwt):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','DowSwt',DowSwt)   # event 类型报文 0xED  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','DowSwt')
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','Bsd_LcaSwt',Bsd_LcaSwt)   # 0xED  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','Bsd_LcaSwt')
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RctaSwt',RctaSwt)   # 0xED  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RctaSwt')
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RctbSwt',RctbSwt)   # 0xED  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RctbSwt')
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RcwSwt',RcwSwt)   # 0xED  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'ICC_0x3FE','RcwSwt')

    def set_signal_RCTA(self,RCTA):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_3','EHC3_Set_RCTA',RCTA)   # event 类型报文0x523 0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_3','EHC3_Set_RCTA')

    def set_signal_RCTB_RCW(self,RCTB,RCW):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_24','EHC24_Set_RCTB',RCTB)   # 0xE1  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_24','EHC24_Set_RCTB')
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_24','EHC24_Set_RCW',RCW)   # 0xE1  0:Inactive;1:ON;2:OFF;3:invalid
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'CDC_EHC_24','EHC24_Set_RCW')

    def set_signal_RctbAvl(self,RctbAvl):
        TSCAN.write_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x183','RctbAvl',RctbAvl)   # 0xE1  0:Available;1:not Available
        TSCAN.read_db_signal(self, Set_up.NetName,Set_up.nodeName,'PBM_0x183','RctbAvl')


    # seed=[104,22,180,213]
    def pad(self, text):
        """
        #填充函数,使被加密数据的字节码长度是block_size的整数倍
        #AES128-ECB PKCS5填充,补齐到16字节,补充12个0xc
        """
        s = ''
        for i in text:
            if i > 15:
                s += hex(i)[2:] # 将seed转化成'6816b4d5'
            else:
                s += '0'
                s += hex(i)[2:]
        logging.info(f's:{s}')
        count = len(text) # seed 固定为4
        add = self.length - (count % self.length) # 所以需要填充12个
        # entext = s + (chr(add) * add)
        entext = s + ('0c'*add)
        return entext

    def calcKey_old(self,seed,level=1):
        factor_level1 = 'CCBA77AAE66C46DCF61FDA35A5BB7049'   # '01020304050607080102030405060708''CCBA77AAE66C46DCF61FDA35A5BB7049' 
        factor_level3 = '62A984BD7D49AB1A7DB243FCBD3EB384'

        factor = factor_level1 if level == 1 else factor_level3
        sha256 = hashlib.sha256(bytes(seed))
        seed1 = sha256.hexdigest().upper() + factor  # '1D26...0708'
        # logging.info(seed1) # seed1 得到拼接数据48字节
        sha256_1 = hashlib.sha256(bytes.fromhex(seed1)) # 通过SHA256对拼接数据运算生成32字节Hash值
        seed2 = sha256_1.hexdigest().upper()[:32]  # 截取32字节Hash值的前16字节作为密钥：9A536A10AF8593BD7967D419C42B5EE0
        # logging.info(seed2)

        self.length = AES.block_size  # 初始化数据块大小
        aes_mode = AES.new(bytes.fromhex(seed2), AES.MODE_ECB)  # 初始化AES,ECB模式的实例

        logging.info(self.pad(seed))
        res = aes_mode.encrypt(bytes.fromhex(self.pad(seed)))  # self.pad(seed)= '6816B4D50C0C0C0C0C0C0C0C0C0C0C0C'  type:str,转换成字节
        key = [int(hex(x), 16) for x in res]
        logging.info(key)
        # logging.info(binascii.b2a_hex(bytearray(key)))
        return key
    
    def calcKey(self,seed,level=1):
        #BE12
        seed = bytearray(seed)
        if level == 1:
            mainkey = unhexlify('824235594325e23a1f2eb53049aa5d66')#('01020304050607080102030405060708')
        else:
            mainkey = unhexlify('65B7EAB1B35C3244E9C05C0262E73C6B')
        df = unhexlify('1F9D6DC2CCF3E59C160081E64E2D8899')
        sk = CMAC.new(mainkey,df,ciphermod=AES)
        sk = unhexlify(sk.hexdigest())
        
        token = CMAC.new(sk,seed,ciphermod=AES)
        # logging.info('1F9D6DC2CCF3E59C160081E64E2D8899'+token.hexdigest())
        token = list(unhexlify(token.hexdigest()))       
        key = list(df)+token
        return key

    def V_ConnectCanH_GND(self, Eanble,iStep):
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:VCANH connects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y0.value,0x0001)
                time.sleep(6)
        else:
            with allure.step(f"Step{iStep}:Remove fault of VCANH connnects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y0.value,0x0000)
            time.sleep(1)
        iStep += 1
        del modbus

        return iStep

    def V_ConnectCanL_Vcc(self, Eanble,iStep):
        
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:VCANH connects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y1.value,0x0001)
                time.sleep(6)
        else:
            with allure.step(f"Step{iStep}:Remove fault of VCANH connnects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y1.value,0x0000)
            time.sleep(1)
        iStep += 1
        del modbus
        return iStep

    def V_ConnectCanH_CanL(self, Eanble,iStep):
        
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:VCANH connects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y2.value,0x0001)
                time.sleep(6)
        else:
            with allure.step(f"Step{iStep}:Remove fault of VCANH connnects to VCANL"):
                modbus.write_single_coil(DO_Address_single.Y2.value,0x0000)
            time.sleep(1)
        iStep += 1
        del modbus
        return iStep

    def P_ConnectCanH_GND(self, Eanble,iStep):
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:SCANH connects to GND"):
                modbus.write_single_coil(DO_Address_single.Y4.value,0x0001)
                time.sleep(6)
        else:
            with allure.step(f"Step{iStep}:Remove fault of SCANH connnects to GND"):
                modbus.write_single_coil(DO_Address_single.Y4.value,0x0000)
            time.sleep(1)
        iStep += 1
        del modbus
        return iStep

    def P_ConnectCanL_Vcc(self, Eanble,iStep):
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:SCANH connects to VCC"):
                modbus.write_single_coil(DO_Address_single.Y5.value,0x0001)
                time.sleep(6)
        else:
            with allure.step(f"Step{iStep}:Remove fault of SCANH connnects to VCC"):
                modbus.write_single_coil(DO_Address_single.Y5.value,0x0000)
            time.sleep(1)
        iStep += 1
        del modbus
        return iStep

    def P_ConnectCanH_CanL(self, Eanble,iStep):
        modbus = Modbus(Set_up.NM_modbusCOM)
        if Eanble:
            with allure.step(f"Step{iStep}:SCANH connects to SCANL"):
                modbus.write_single_coil(DO_Address_single.Y6.value,0x0001)
                time.sleep(6)
                logging.info('Unicom SFCAN CanH_CanL,Wait 6s')
        else:
            with allure.step(f"Step{iStep}:Remove fault of SCANH connnects to SCANL"):
                modbus.write_single_coil(DO_Address_single.Y6.value,0x0000)
                logging.info('Disconnect SFCAN CanH_CanL')
            time.sleep(1.5)
        iStep += 1
        del modbus
        return iStep


    def SetVolt(self, Driver, VoltNumber, waitTime, iStep):
        with allure.step(f"Step{iStep}:Set voltage = {VoltNumber}V"):
            Driver['power'].set_vltage(VoltNumber)
        iStep += 1
        time.sleep(waitTime)
        Driver['power'].Read_Measure()
        return iStep

    def reportNumberOfDTCByStatusMask(self,data,value):
        """
        反馈 通过状态掩码读DTC的个数
        方案:实际的DTC 状态掩码与上19 01后面的状态掩码的值 大于0的个数
        """
        DTC_data = np.array(data)[3:].reshape((-1,4)).tolist()
        DTC_status = [i[-1] for i in DTC_data]
        And_operation = list(map(lambda x:x & value,DTC_status))
        num = int(hex(len(([n for n in And_operation if n > 0 ]))),16)

        return num

    '''转换字符串为数组'''
    def strToToHexBytes(self,hexString):
        hexString = str(hexString).replace(' ', '').replace('[', '').replace(']', '').replace('\'', '')

        if ((len(hexString) % 2) != 0):
            hexString += " "

        c_16_temp = list(hexString)
        ilen = int(len(c_16_temp) / 2)
        hexBytes = [0] * ilen
        for index in range(ilen):
            hexBytes[index] = int((c_16_temp[2 * index] + c_16_temp[2 * index + 1]),16)
        return hexBytes
   
    def unlock(self,Driver, iStep):
        try:
            seed = []
            with allure.step(f"Step{iStep}:Request:0x27 0x01, # Response:0x67,0x01"):
                uds_rep,size = Driver['UDS'].req_and_res_can([0x27,0x01],2)
                with assume: assert (uds_rep[0:2] == [0x67,0x01] and size == 18)
            
                for i in range(len(uds_rep)-2):
                    seed.append(uds_rep[2+i])
            
                key = Driver['CAN'].calcKey(seed)
                send_key = [0x27,0x02] + key

            iStep = iStep + 1
            with allure.step(f"Step{iStep}:Request:{0}, # Response:0x67,0x02".format(send_key)):
                uds_rep,size = Driver['UDS'].req_and_res_can(send_key,len(send_key))
                with assume: assert uds_rep[0:2] == [0x67,0x02]
            
            return iStep + 1
        except Exception as e:
            logging.info(f"{e}".center(50, '-'))

    def unlock_3(self,Driver, iStep):
        try:
            seed = []
            with allure.step(f"Step{iStep}:Request:0x27 0x11, # Response:0x67,0x11"):
                uds_rep,size = Driver['UDS'].req_and_res_can([0x27,0x11],2)
                with assume: assert (uds_rep[0:2] == [0x67,0x11] and size == 18)
            
                for i in range(len(uds_rep)-2):
                    seed.append(uds_rep[2+i])
            
                key = Driver['CAN'].calcKey(seed,3)
                send_key = [0x27,0x12] + key

            iStep = iStep + 1
            with allure.step(f"Step{iStep}:Request:{0}, # Response:0x67,0x12".format(send_key)):
                uds_rep,size = Driver['UDS'].req_and_res_can(send_key,len(send_key))
                with assume: assert uds_rep[0:2] == [0x67,0x12]
            
            return iStep + 1
        except Exception as e:
            logging.info(f"{e}".center(50, '-'))

    ''' Reqstr=发送信息 Respstr=接收信息 session=会话模式 iStep=步骤几 unlock=会话模式切换完成是否需要安全认证'''
    def checkReqResp(self, Driver, Reqstr, Respstr, session, iStep, unlock=False, addressing='UDS', isClearFault='noClearFault', unlock_level=1):

        # 判断传入变量类型
        if isinstance(Reqstr, str):
            req = self.strToToHexBytes(Reqstr)
        else:
            req = Reqstr
        if isinstance(Respstr, str):
            resp = self.strToToHexBytes(Respstr)
        else:
            resp = Respstr

        # 会话模式
        if session==1 or session==3 or session == 2:
            with allure.step(f'Step{iStep}: Request 0x10 0x01 # Response: 0x50,0x01'):
                uds_resp, size = Driver['UDS'].req_and_res_can([0x10, 0x01], 2)
                with assume:assert uds_resp[0:2] == [0x50, 0x01]
                iStep = iStep + 1
                time.sleep(0.5)
        if session == 3 or session == 2:
            with allure.step(f'Step{iStep}: Request 0x10 0x03 # Response: 0x50,0x03'):
                uds_resp, size = Driver['UDS'].req_and_res_can([0x10, 0x03], 2)
                with assume:assert uds_resp[0:2] == [0x50, 0x03]
                iStep = iStep + 1
                time.sleep(0.5)
        if session==2:
            # iStep = self.unlock(Driver, iStep)
            with allure.step(f'Step{iStep}: Request 0x10 0x02 # Response: 0x50,0x02'):
                uds_resp, size = Driver['UDS'].req_and_res_can([0x31, 0x01, 0x02, 0x03], 4)
                with assume:assert uds_resp[0:2] == [0x71, 0x01]
                time.sleep(0.5)
                iStep = iStep + 1
            with allure.step(f'Step{iStep}: Request 0x10 0x02 # Response: 0x50,0x02'):
                uds_resp, size = Driver['UDS'].req_and_res_can([0x10, 0x02], 2)
                with assume:assert uds_resp[0:2] == [0x50, 0x02]
                iStep = iStep + 1
                time.sleep(2)
        if unlock:
            if unlock_level == 1 and session != 2:
                iStep = self.unlock(Driver, iStep)
            elif unlock_level == 3 or session == 2:
                iStep = self.unlock_3(Driver, iStep)

        '''清除故障''' 
        if isClearFault != 'noClearFault':
            with allure.step(f"Step{iStep}:Request 0x14 0xFF 0xFF 0xFF # Response: 0x54"):
                uds_rep, size = Driver['UDS'].req_and_res_can([0x14, 0xFF, 0xFF, 0xFF], 4)
                iStep +=1 
                reqstr = binascii.b2a_hex(bytearray(uds_rep), ' ')
                with assume: assert uds_rep[0] == 0x54
                iStep +=1 
                time.sleep(2)

        reqstr = binascii.b2a_hex(bytearray(req), ' ')
        respstr = binascii.b2a_hex(bytearray(resp), ' ')

        with allure.step(f'Step{iStep}: Request {reqstr} # Response: {respstr}'): 
            uds_resp, size = Driver[addressing].req_and_res_can(req, len(req))

            if len(resp) == 0 :
                with assume: assert 0 == size
            elif len(uds_resp) == 0:
                with assume: assert len(resp) == size
                corrRespStr = binascii.b2a_hex(bytearray(resp), ' ')
                actuRespStr = binascii.b2a_hex(bytearray(uds_resp[0:len(uds_resp)]), ' ')   
                logging.error(f'correct response:[{corrRespStr}], actual response:[{actuRespStr}]') 
            else:    
                if uds_resp[0:len(resp)] != resp:
                    corrRespStr = binascii.b2a_hex(bytearray(resp), ' ')
                    actuRespStr = binascii.b2a_hex(bytearray(uds_resp[0:len(uds_resp)]), ' ')   
                    logging.error(f'correct response:[{corrRespStr}], actual response:[{actuRespStr}]')  
                with assume: assert uds_resp[0:len(resp)] == resp
                if req == [0x27,0x01] and resp[0] != 0x7F:
                    assert size == 18
                if req == [0x27,0x11] and resp[0] != 0x7F:
                    assert size == 18
                if req == [0x27,0x03] and resp[0] != 0x7F:
                    assert size == 18
                
                if req == [0x11,0x01] or req == [0x11,0x03]:
                    time.sleep(1)

        return iStep + 1,uds_resp, size


    def restartMRR_Power(self,Driver, iStep=1):
        with allure.step(f'Step{iStep}:ECU下电再次上电'):
            logging.info('设置钥匙信号为0x00--off')
            time.sleep(0.5)
            self.wakeup_ctrl(False)
            logging.info('wait 10s for ecu sleep')
            time.sleep(10)
            Driver['power'].Enable(False)
            logging.info('Power off the ECU')
            time.sleep(1)
            Driver['power'].Enable(True)
            logging.info('Wait 1s, Power on the ECU')
            self.wakeup_ctrl(True)
            time.sleep(5)
            logging.info('Wait 5s, Restart the device OK')
            iStep += 1
        return iStep

    def restartMRR_11(self,Driver, iStep=1):
        with allure.step(f'Step{iStep}:request 1101 restart ECU'):
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName, 'PEPS_0x1B1', 'PwrMod', 0)
            time.sleep(0.5)
            Driver['CAN'].checkReqResp(Driver, "11 01", "51 01", 0, iStep, False)
            time.sleep(2)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName, 'PEPS_0x1B1', 'PwrMod', 2)
            time.sleep(1)
            logging.info('Wait 2s, Restart the device OK')
            iStep += 1
        return iStep

    def wakeup_ctrl(self,enable):
        if enable:
            self.set_signal_IGN(2)
            logging.info('start NM message')
            self.wake_ref = self.send_CANFrame_Cycle(0x44C,[0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00],500)
            # self.wake_ref = self.send_CANFrame_Cycle(0x411,[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],500)
        else:
            self.set_signal_IGN(0)
            logging.info('stop NM message')
            self.stop_FrANFrame_Cycle(self.wake_ref)
            
        pass

    def vechile_message(self,Driver,flag):
        #BE12
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'AVAP_0x195',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'EPS_0x150',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'PBM_0x183',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'PBM_0x185',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'PBM_0x186',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'YRS_0x19A',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'PBM_0x1A6',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'ICC_0x3FE',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x230',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'BCM_0x2D2',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'ICM_0x2E0',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'ECC_AAC_0x3F2',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'TBOX_0x551',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'ICC_0x31F',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'VCU_PDCU_0x6C0',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'VCU_MCU_PDCU_0x210',Enalbe=flag)
        Driver['CAN'].Enable_rbs_message(Set_up.NetName,Set_up.nodeName,'CIM_0x1D0',Enalbe=flag)

    
    '''判断除了三个初始故障是否有新的故障产生'''
    def delInitialFailure(self, iStep,data):
        current_DTC = []
        for real_reponse in np.array(data[3:]).reshape(-1,4):
                    current_DTC.append(real_reponse[0:4].tolist())

        with allure.step(f'Step{iStep}: Determine whether there is any other DTC'):
            for m in Set_up.InitialFailure:
                if m in current_DTC:
                    current_DTC.remove(m)
            with assume: assert len(current_DTC) == 0


            actuRespStr = []
            if len(current_DTC) != 0:
                for m in current_DTC:
                    actuRespStr.append(binascii.b2a_hex(bytearray(m), ' '))

                logging.error('Should not exist DTC iS:[{0}]'.format(actuRespStr)) 
            iStep += 1
        
        return iStep

    def split_list_by_size(Self, original_list, chunk_size):
        return [original_list[i:i + chunk_size] for i in range(0, len(original_list), chunk_size)]

    
    def SendAndRead_Eol(self, Driver, send_ID, send_Data, receive_ID, timesleep = 0.08, CanType='CAN'):
        sendstr = binascii.b2a_hex(bytearray(send_Data),' ')
        logging.info('send_ID =    [{0:X}], send_Data =    [{1}]'.format(send_ID, sendstr))
        Driver['CAN2'].fush_q_buff()  # 清缓存
        Driver['CAN2'].send_Frame(send_ID,send_Data,CanType)
        time.sleep(timesleep)
        ALl_data,buffer_size = Driver['CAN2'].read_frame()
        response_data = ALl_data[ALl_data['AIdentifier']== receive_ID]
        receive_data = []
        try:
            len = response_data.iloc[0]['ADLC']
            if len < 9:
                lenth = 8 
            if len == 9:
                lenth = 12
            if len == 10:
                lenth = 16
            if len == 11:
                lenth = 20
            if len == 12:
                lenth = 24
            if len == 13:
                lenth = 32
            if len == 14:
                lenth = 48
            if len == 15:
                lenth = 64
            last_data = response_data.iloc[0]['ADatas'] 
            
            receive_data = last_data[0:lenth]
        except:
            receive_data = []
            # logging.info('[0x{0:X}] no response'.format(receive_ID))

        readstr = binascii.b2a_hex(bytearray(receive_data),' ')
        logging.info('receive_ID = [{0:X}], receive_Data = [{1}]'.format(receive_ID,readstr))
        
        return receive_data

# run main
if __name__ == "__main__":
    import os
    root = os.getcwd()
    project_DBC_File_CAN = os.path.join(root, r'data\BJEV_ADASBUS_CMRR_RR_CANFD_V1.5_20240308.dbc')
    logging.info(project_DBC_File_CAN)
    try:
        rbs = real_CAN(drive_type = 'USE_TS_TC1014_DEVICE',    # USE_TS_TC1014_DEVICE /   USE_TS_VIRTUAL_DEVICE
                    configure_baudrate = {'CAN_Type':'CANFD','ArbRate':500,'DataRate':2000,'TermResistor':True}
                    )
        rbs.load_dbc(project_DBC_File_CAN)
        # rbs.register_event_can_T_R(OnCANevent)
        # rbs.register_event_canfd_T_R(OnCANFDevent)
        # rbs.set_0x127_rolling_counter_error(enable=False)
        # rbs.register_event_canfd_T_pre(OnCANPreFDevent)
        
        rbs.connect_application()
        rbs.RBS_Config('BE12A',[Set_up.nodeName])

        logging.info('send frame')
        rbs.send_Frame(0x666,[0x61,2,3,4,5,6,7,8,
                              0x22,2,3,4,5,6,7,8,
                              0x23,2,3,4,5,6,7,8,
                              0x24,2,3,4,5,6,7,8,
                              0x25,2,3,4,5,6,7,8,
                              0x26,2,3,4,5,6,7,8,
                              0x27,2,3,4,5,6,7,8,
                              0x28,2,3,4,5,6,7,8],'CANFD')
        rbs.send_Frame(0x777,[0x71,2,3,4,5,6,7,8,],'CAN')
        rbs.send_Frame(0x777,[0x81,2,3,4,5,6,7,8,],'CAN')
        rbs.send_Frame(0x444,[0x41,2,3,4,5,6,7,8,],'CAN')

        a =rbs.send_CANFrame_Cycle(0x22,[0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88],100)
        
        logging.info('step1_wait_1000_:::::')
        rbs.fush_q_buff()
        rbs.TS_delay(1000)
        rbs.read_frame()

        logging.info('step2__wait_2000_:::::') 
        rbs.fush_q_buff()
        rbs.TS_delay(2000)
        rbs.read_frame()

        logging.info('step2__wait_2000_:::::') 
        rbs.fush_q_buff()
        rbs.TS_delay(2000)
        rbs.read_frame()

        logging.info('step3__wait_3000_:::::') 
        rbs.fush_q_buff()
        rbs.TS_delay(3000)
        rbs.read_frame()

        ttttt = rbs.sendAndread_CMD_Shell(0x114,'test 12',500)
        ttttt = rbs.sendAndread_CMD_Shell(0x114,'test 12',500)
        logging.info(ttttt)
        rbs.stop_FrANFrame_Cycle(a)

        rbs.write_db_signal('BE12A',Set_up.nodeName,'BCM_0x2D2','BDCExtrLampSts',1)

        aa = rbs.read_db_signal('BE12A',Set_up.nodeName,'BCM_0x2D2','BDCExtrLampSts')
        logging.info('read rbs signal value is ',aa)

        # diag = TSCAN_UDS()
        # diag.req_and_res_can([0x22,0xf1,0x90],3)
        # diag.UDS_can_delete()

        # obj = HIL_Obj(rbs)
        # obj.setDaemon(True)
        # obj.open()
        # obj.obj_sent()
        # obj.start()
        # obj.last_warninh_data
        # obj.warning_data

        rbs.dis_connect_application()

        logging.info('Over All')
        import sys
        sys.exit(0)

    except Exception as e :
        rbs.dis_connect_application()
        import sys
        import traceback
        logging.info(traceback.print_exc())
        sys.exit(0)
        pass
    
    except KeyboardInterrupt :
        rbs.dis_connect_application()
        import sys
        import traceback
        logging.info(traceback.print_exc())
        sys.exit(0)
        pass


